package com.suncaper.han_yi_system.config;


import com.suncaper.han_yi_system.filter.JwtAuthenticationTokenFilter;
import com.suncaper.han_yi_system.handle.AccessDeniedHandlerImpl;
import com.suncaper.han_yi_system.handle.AuthenticationEntryPointImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity// 开启SpringSecurity的Web安全模式
public class SecurityConfig {

    private final JwtAuthenticationTokenFilter jwtAuthFilter;

    private final AuthenticationEntryPointImpl authenticationEntryPoint;

    private final AccessDeniedHandlerImpl accessDeniedHandler;

    // 注入JwtAuthenticationTokenFilter（构造器注入）
    public SecurityConfig(JwtAuthenticationTokenFilter jwtAuthFilter,
                          AuthenticationEntryPointImpl authenticationEntryPoint,
                          com.suncaper.han_yi_system.handle.AccessDeniedHandlerImpl accessDeniedHandler) {
        this.jwtAuthFilter = jwtAuthFilter;
        this.authenticationEntryPoint = authenticationEntryPoint;
        this.accessDeniedHandler = accessDeniedHandler;
    }

    // 密码编码器
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    // 暴露 AuthenticationManager
    @Bean
    public AuthenticationManager authenticationManager(
            AuthenticationConfiguration authConfig) throws Exception {
        return authConfig.getAuthenticationManager();
    }

    // 完全忽略指定路径（不经过任何过滤器）
    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return web -> web.ignoring()
                .requestMatchers(
                        "/acc/login",
                        "/api/captcha",
                        "/swagger-ui/**",// Swagger UI 页面
                        "/v3/api-docs",           // OpenAPI 文档端点
                        "/v3/api-docs/**",        // OpenAPI 文档子路径
                        "/swagger-resources/**",  // Swagger 资源文件
                        "/webjars/**"
                );
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

        http
                // 关闭csrf
                .csrf(AbstractHttpConfigurer::disable)
                // 不通过Session获取SecurityContext
                .sessionManagement(session ->
                        session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                )
                // 请求授权的配置
                .authorizeHttpRequests(auth ->auth
//                        .requestMatchers( "/swagger-ui/**",// Swagger UI 页面
//                                "/v3/api-docs",           // OpenAPI 文档端点
//                                "/v3/api-docs/**",        // OpenAPI 文档子路径
//                                "/swagger-resources/**",  // Swagger 资源文件
//                                "/webjars/**" ).permitAll()
                        .anyRequest().permitAll()//.authenticated()
                )
                // 添加JWT过滤器
                .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
                // 自定义异常处理器
                .exceptionHandling(exceptions -> exceptions
                        .accessDeniedHandler(accessDeniedHandler)
                        .authenticationEntryPoint(authenticationEntryPoint)
                )
        ;

        return http.build();

    }

}
